_require local "../../../../basis.smi"

_require local "../../debug/main/Bug.smi"
_require local "../../format-utils/main/TermPrintUtils.ppg.smi"

_require "../../../../smlformat-lib.smi"

_require "../../../data/symbols/main/Symbol.smi"
_require "../../../data/symbols/main/RecordLabel.smi"
_require "../../../data/symbols/main/Loc.smi"
_require "../../../libs/ids/main/LocalID.smi"
_require "../../../libs/env/main/SEnv.smi"
_require "../../../libs/env/main/IEnv.smi"
_require local "../../../libs/util/main/TermFormat.smi"
_require local "../../../libs/toolchain/main/Filename.smi"

structure ReifiedTy =
struct
  type btvId = BoundTypeVarID.id
  type typId = TypID.id
  exception ConSetNotFound

  val ptrSize : word

  datatype taggedLayout 
    = TAGGED_RECORD of {tagMap: int SEnv.map}
    | TAGGED_OR_NULL of {tagMap: int SEnv.map, nullName: string}
    | TAGGED_TAGONLY of {tagMap: int SEnv.map}

  val taggedLayoutToString : taggedLayout -> string
  val taggedLayoutEq : taggedLayout * taggedLayout -> bool
  datatype layout
    = LAYOUT_TAGGED of taggedLayout
    | LAYOUT_ARG_OR_NULL of {wrap: bool}
    | LAYOUT_SINGLE_ARG of {wrap: bool}
    | LAYOUT_CHOICE of {falseName: string}
    | LAYOUT_SINGLE
  val layoutToString : layout -> string
  val layoutEq : layout * layout -> bool

  datatype reifiedTy
    = ARRAYty of reifiedTy
    | BOOLty
    | BOTTOMty
    | BOUNDVARty of BoundTypeVarID.id
    | BOXEDty
    | CHARty
    | CODEPTRty
    | CONSTRUCTty of {longsymbol: Symbol.longsymbol, id:TypID.id, args:reifiedTy list, conSet:reifiedTy option SEnv.map, layout:layout, size:int}
    | DATATYPEty of {longsymbol: Symbol.longsymbol, id:TypID.id, args:reifiedTy list, layout:layout, size:int}
    | DUMMYty of {boxed : bool, size : word}
    | DYNAMICty of reifiedTy
    | ERRORty
    | EXISTty of {boxed : bool option, size : word option, id : int}
    | EXNTAGty
    | EXNty
    | FUNMty of reifiedTy list * reifiedTy
    | IENVMAPty of reifiedTy
    | INT16ty
    | INT32ty
    | INT64ty
    | INT8ty
    | INTERNALty
    | INTINFty
    | LISTty of reifiedTy
    | OPAQUEty of {longsymbol: Symbol.longsymbol, id:TypID.id, args:reifiedTy list, boxed:bool, size:int}
    | OPTIONty of reifiedTy
    | POLYty of {boundenv: btvId BoundTypeVarID.Map.map, body:reifiedTy}
    | PTRty of reifiedTy
    | REAL32ty
    | REAL64ty
    | RECORDLABELMAPty of reifiedTy
    | RECORDLABELty 
    | RECORDty of reifiedTy RecordLabel.Map.map
    | REFty of reifiedTy
    | SENVMAPty of reifiedTy
    | STRINGty
    | TYVARty
    | UNITty 
    | VECTORty of reifiedTy
    | VOIDty
    | WORD16ty
    | WORD32ty
    | WORD64ty
    | WORD8ty

  type conSet = reifiedTy option SEnv.map
  datatype void = void
  val format_reifiedTy : reifiedTy -> SMLFormat.format
  val reifiedTyToString : reifiedTy -> string
  val printTy : reifiedTy -> unit
  val reifiedTyEq : reifiedTy * reifiedTy -> bool
  val reifiedTyEq' : reifiedTy * reifiedTy -> reifiedTy IEnv.map option

  val emptyConSet : conSet

  val format_conSet : conSet -> SMLFormat.format
  val conSetToString : conSet -> string
  val conSetEq : conSet * conSet -> bool

  type conSetEnv = conSet TypID.Map.map
  val emptyConSetEnv : conSetEnv
  val format_conSetEnv : conSetEnv -> SMLFormat.format
  val conSetEnvToString : conSetEnv -> string
  val conSetEnvEq : conSetEnv * conSetEnv -> bool

  type tyRep = {conSetEnv: conSetEnv, reifiedTy : reifiedTy}
  val format_tyRep : tyRep -> SMLFormat.format
  val tyRepToString : tyRep -> string
  val tyRepEq : tyRep * tyRep -> bool

  val globalConSetEnv : conSetEnv ref
  val resetGlobalConSetEnv : unit -> unit
  val getGlobalConSetEnv : unit -> conSetEnv
  val lookUpConSet : conSetEnv * TypID.id -> conSet
  val findConSet : TypID.id -> conSet option
  val mkConSet : (string * reifiedTy option) list -> conSet
  val insertConSet : conSetEnv * TypID.id * conSet -> conSetEnv
  val setConSet : TypID.id * conSet -> unit

  val getConstructTy : tyRep -> tyRep
  val getConSet : tyRep -> conSet
  val instantiate : reifiedTy * reifiedTy list -> reifiedTy

  val stringReifiedTyListToRecordTy : (string * reifiedTy) list -> reifiedTy
  val stringReifiedTyOptionListToConSet : (string * reifiedTy option) list -> conSet
  val makePos : bool -> bool -> string option -> int -> int -> int -> int ->  Loc.pos
  val typIdConSetListToConSetEnv : (TypID.id * conSet) list -> conSetEnv
  val TyRep : conSetEnv -> reifiedTy -> tyRep
  val TyRepToReifiedTy : tyRep -> reifiedTy 
  val MergeConSetEnvWithTyRepList : conSetEnv -> tyRep list -> conSetEnv
  val btvIdBtvIdListToBoundenv : (btvId * btvId) list -> btvId BoundTypeVarID.Map.map
  val boundenvReifiedTyToPolyTy : btvId BoundTypeVarID.Map.map -> reifiedTy -> reifiedTy
  val makeDummyTy : bool -> word -> reifiedTy
  val makeExistTy : bool option -> word option -> int -> reifiedTy
  val makeFUNMty : reifiedTy list -> reifiedTy -> reifiedTy
  val boolToWrapRecord : bool -> {wrap:bool}
  val stringToFalseNameRecord : string -> {falseName:string}
  val stringIntListToTagMap : (string * int) list -> int SEnv.map
  val tagMapStringToTagMapNullNameRecord : (int SEnv.map) -> string -> {tagMap:int SEnv.map, nullName:string}
  val tagMapToTagMapRecord : (int SEnv.map) -> {tagMap:int SEnv.map}
  val longsymbolIdArgsLayoutListToDatatypeTy : Symbol.longsymbol -> TypID.id -> reifiedTy list -> layout -> int -> reifiedTy
  val longsymbolIdArgsToOpaqueTy : Symbol.longsymbol -> TypID.id -> reifiedTy list -> int -> bool -> reifiedTy

  val sizeOf : reifiedTy -> word
  val isGroundTy : reifiedTy -> bool
  val isBaseTy : reifiedTy -> bool

end
